﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Collections;
using System.Linq;
using System.IO;
using System.Threading;
//using System.Xml.Linq;


namespace CommonUtils
{
	public class CMyDataSet
	{
		#region // Constructors and Destructors:
		public const string c_strKey_DataSetName_CMyDataSet = "c_strKey_DataSetName_CMyDataSet";
		public const string c_strKey_DataTableName_SysInfo = "c_strKey_DataTableName_SysInfo";
		public const string c_strKey_DataTableName_SysError = "c_strKey_DataTableName_SysError";
		public const string c_strKey_ColumnName_Tid = "Tid";
		public const string c_strKey_ColumnName_DigitalSignature = "DigitalSignature";
		public const string c_strKey_ColumnName_ErrorCode = "ErrorCode";
		public const string c_strKey_ColumnName_Remark = "Remark";
		public const string c_strKey_ColumnName_FlagCompress = "FlagCompress";
		public const string c_strKey_ColumnName_FlagEncrypt = "FlagEncrypt";
		public const string c_strKey_ColumnName_ParamCode = "ParamCode";
		public const string c_strKey_ColumnName_ParamValue = "ParamValue";

		public static DataSet NewMyDataSet()
		{
			return CMyDataSet.NewMyDataSet("", "");
		}
		public static DataSet NewMyDataSet(string strTid)
		{
			return CMyDataSet.NewMyDataSet(strTid, "");
		}
		public static DataSet NewMyDataSet(
			string strTid
			, string strDigitalSignature
			)
		{
			// Temp:
			DataSet mds = new DataSet(c_strKey_DataSetName_CMyDataSet);

			// dtSysInfo:
			DataTable dtSysInfo = new DataTable(c_strKey_DataTableName_SysInfo); mds.Tables.Add(dtSysInfo);
			dtSysInfo.Columns.Add(c_strKey_ColumnName_Tid, typeof(string));
			dtSysInfo.Columns.Add(c_strKey_ColumnName_DigitalSignature, typeof(string));
			dtSysInfo.Columns.Add(c_strKey_ColumnName_ErrorCode, typeof(string));
			dtSysInfo.Columns.Add(c_strKey_ColumnName_Remark, typeof(string));
			dtSysInfo.Columns.Add(c_strKey_ColumnName_FlagCompress, typeof(string));
			dtSysInfo.Columns.Add(c_strKey_ColumnName_FlagEncrypt, typeof(string));
			dtSysInfo.Rows.Add(new object[] {
				strTid // Tid
				, strDigitalSignature // DigitalSignature
				, "0" // ErrorCode
				, "" // Remark
				, "0" // FlagCompress
				, "0" // FlagEncrypt
			});

			// dtSysError:
			DataTable dtSysError = new DataTable(c_strKey_DataTableName_SysError); mds.Tables.Add(dtSysError);
			dtSysError.Columns.Add(c_strKey_ColumnName_ParamCode, typeof(string));
			dtSysError.Columns.Add(c_strKey_ColumnName_ParamValue, typeof(object));

			// Return Good:
			mds.AcceptChanges();
			return mds;
		}
		#endregion

		#region // Public members:
		public static bool IsMyDataSet(DataSet mds)
		{
			return (mds != null) && string.Equals(mds.DataSetName, c_strKey_DataSetName_CMyDataSet);
		}
		public static bool HasError(DataSet mds)
		{
			if (mds == null)
				return true;
			return !string.Equals(mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_ErrorCode], "0");
		}

		public static object GetTid(DataSet mds)
		{
			return mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_Tid];
		}
		public static void SetTid(ref DataSet mds, object strValue)
		{
			mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_Tid] = strValue;
		}

		public static object GetDigitalSignature(DataSet mds)
		{
			return mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_DigitalSignature];
		}
		public static void SetDigitalSignature(ref DataSet mds, object strValue)
		{
			mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_DigitalSignature] = strValue;
		}

		public static object GetErrorCode(DataSet mds)
		{
			return mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_ErrorCode];
		}
		public static void SetErrorCode(ref DataSet mds, object strValue)
		{
			mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_ErrorCode] = strValue;
		}

		public static object GetRemark(DataSet mds)
		{
			return mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_Remark];
		}
		public static void SetRemark(ref DataSet mds, object strValue)
		{
			mds.Tables[c_strKey_DataTableName_SysInfo].Rows[0][c_strKey_ColumnName_Remark] = strValue;
		}
	
		public static object[] GetErrorParams(DataSet mds)
		{
			ArrayList alPairedParams = new ArrayList();
			DataTable dt = mds.Tables[c_strKey_DataTableName_SysError];
			for (int i = 0; i < dt.Rows.Count; i++)
				alPairedParams.AddRange(dt.Rows[i].ItemArray);
			return alPairedParams.ToArray();
		}
		public static void SetErrorParams(ref DataSet mds, params object[] arrobjParamsCouple)
		{
			mds.Tables.Remove(c_strKey_DataTableName_SysError);
			DataTable dt = new DataTable(c_strKey_DataTableName_SysError);
			dt.Columns.Add(c_strKey_ColumnName_ParamCode, typeof(string));
			dt.Columns.Add(c_strKey_ColumnName_ParamValue, typeof(object));
			mds.Tables.Add(dt);
			if (arrobjParamsCouple == null || arrobjParamsCouple.Length == 0) return;
			for (int i = 0; i < arrobjParamsCouple.Length; i += 2)
			{
				dt.Rows.Add(arrobjParamsCouple[i], arrobjParamsCouple[i + 1]);
			}
		}
		public static void AppendErrorParams(ref DataSet mds, params object[] arrobjParamsCouple)
		{
			if (arrobjParamsCouple == null || arrobjParamsCouple.Length == 0) return;
			DataTable dt = mds.Tables[c_strKey_DataTableName_SysError];
			for (int i = 0; i < arrobjParamsCouple.Length; i += 2)
			{
				dt.Rows.Add(arrobjParamsCouple[i], arrobjParamsCouple[i + 1]);
			}
		}
		#endregion
	}

	public class CMyException
	{
		#region // Constructors and Destructors:
		private const string c_strKeyID = "CMyException";
		private const string c_strKeyErrorCode = "ErrorCode";
		private const string c_strKeyData = "Data";
		#endregion

		#region // Public members:
		public static Exception Raise(
			string strErrorCode
			, Exception excInner
			, params object[] arrobjParamsCouple
			)
		{
			string strExc = string.Format("CMyException [{0}]", strErrorCode);
			Exception exc = new Exception(strErrorCode, excInner);
			exc.Data.Add(c_strKeyID, c_strKeyID);
			exc.Data.Add(c_strKeyErrorCode, strErrorCode);
			exc.Data.Add(c_strKeyData, arrobjParamsCouple);

			return exc;
		}
		public static bool IsMyException(Exception exc)
		{
			if (exc == null) return false;
			return (string.Equals(exc.Data[c_strKeyID], c_strKeyID));
		}
		public static string GetErrorCode(Exception exc)
		{
			return Convert.ToString(exc.Data[c_strKeyErrorCode]);
		}
		public static object[] GetErrorParams(Exception exc)
		{
			return (object[])(exc.Data[c_strKeyData]);
		}
		#endregion
	}

	public class CSessionManager
	{
		#region // Constructors and Destructors:
		private DataTable _dtSession = null;
		private Hashtable _htSessionMap = new Hashtable();
		private long _nSeq = 0;
		public CSessionManager()
		{
			_dtSession = new DataTable("Lic_Session");
			_dtSession.Columns.Add("SessionId", typeof(string));
			_dtSession.Columns.Add("PartnerCode", typeof(string));
			_dtSession.Columns.Add("PartnerUserCode", typeof(string));
			_dtSession.Columns.Add("LanguageCode", typeof(string));
			_dtSession.Columns.Add("UserCode", typeof(string));
			_dtSession.Columns.Add("DateTimeLogin", typeof(string));
			_dtSession.Columns.Add("DateTimeLastAccess", typeof(string));
			_dtSession.Columns.Add("OtherInfo", typeof(string));
			_dtSession.AcceptChanges();
		}
		#endregion

		#region // Public members:
		public string SessionAdd(
			string strPartnerCode
			, string strPartnerUserCode
			, string strLanguageCode
			, string strUserCode
			, string strOtherInfo
			)
		{
			// Init:
			string strSessionId = "";

			// Process:
			lock (_htSessionMap)
			{
				// Create new Session:
				strSessionId = string.Format("{0}.{1}", DateTime.Now.ToString("yyyyMMdd.HHmmss.ffffff"), _nSeq++ % 100);
				DataRow drSession = _dtSession.NewRow(); _dtSession.Rows.Add(drSession);
				drSession["SessionId"] = strSessionId;
				drSession["PartnerCode"] = strPartnerCode;
				drSession["PartnerUserCode"] = strPartnerUserCode;
				drSession["LanguageCode"] = strLanguageCode;
				drSession["UserCode"] = strUserCode;
				drSession["DateTimeLogin"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
				drSession["DateTimeLastAccess"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
				drSession["OtherInfo"] = strOtherInfo;
				_dtSession.AcceptChanges();
				_htSessionMap.Add(strSessionId, drSession);
			}

			// Return Good:
			return strSessionId;
		}
		public bool SessionRemove(string strSessionId)
		{
			// Check:
			if (!_htSessionMap.ContainsKey(strSessionId)) return false;

			// Process:
			lock (_htSessionMap)
			{
				DataRow drSession = (DataRow)_htSessionMap[strSessionId];
				if (drSession == null) return false;
				_htSessionMap.Remove(strSessionId);
				_dtSession.Rows.Remove(drSession);
			}

			// Return Good:
			return true;
		}
		public bool SessionSetLastAccess(string strSessionId)
		{
			// Check:
			if (!_htSessionMap.ContainsKey(strSessionId)) return false;

			// Process:
			lock (_htSessionMap)
			{
				DataRow drSession = (DataRow)_htSessionMap[strSessionId];
				if (drSession == null) return false;
				drSession["DateTimeLastAccess"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
			}

			// Return Good:
			return true;
		}
		public DataTable GetAllSessionInfo()
		{
			return _dtSession;
		}
		public DataRow GetSessionInfo(string strSessionId)
		{
			return (DataRow)_htSessionMap[strSessionId];
		}

		#endregion
	}

	public class CMyHashTable
	{
		#region // Constructors and Destructors:
		private Hashtable _htMapValue = new Hashtable();
		private Hashtable _htMapKey = new Hashtable();
		#endregion

		#region // Public members:
		public void AddVectorKey(object strKeyVectorName, ArrayList alVectorKey)
		{
			ArrayList alValues = new ArrayList(alVectorKey);
			Hashtable htKeys = new Hashtable();
			for (int i = 0; i < alValues.Count; i++)
			{
				htKeys.Add(alValues[i], i);
			}
			_htMapValue.Add(strKeyVectorName, alValues);
			_htMapKey.Add(strKeyVectorName, htKeys);
		}
		public void AddVectorValue(object strValueVectorName, ArrayList alVectorValue)
		{
			ArrayList alValues = new ArrayList(alVectorValue);
			_htMapValue.Add(strValueVectorName, alValues);
		}
		public void ClearVector(object strVectorName)
		{
			_htMapValue.Remove(strVectorName);
			_htMapKey.Remove(strVectorName);
		}
		public void ClearAll()
		{
			_htMapValue.Clear();
			_htMapKey.Clear();
		}
		public CMyHashTable CloneShallow()
		{
			// Init:
			CMyHashTable mht = new CMyHashTable();
			ArrayList alKeyVectorName = this.GetAllKeyVectorName();
			ArrayList alAllVectorName = this.GetAllVectorName();

			// Init AllKeyVector:
			for (int i = 0; i < alKeyVectorName.Count; i++)
			{
				mht.AddVectorKey(alKeyVectorName[i], this.GetVector(alKeyVectorName[i]));
			}

			// Init AllValueVector:
			for (int i = 0; i < alAllVectorName.Count; i++)
			{
				if (!alKeyVectorName.Contains(alAllVectorName[i]))
				{
					mht.AddVectorValue(alAllVectorName[i], this.GetVector(alAllVectorName[i]));
				}
			}

			// Return Good:
			return mht;
		}
		public bool ContainsVector(object strVectorName)
		{
			return _htMapValue.ContainsKey(strVectorName);
		}
		public bool IsKeyVector(object strVectorName)
		{
			return _htMapKey.ContainsKey(strVectorName);
		}
		public bool ContainsKey(object strKeyVectorName, object objKey)
		{
			Hashtable htKeys = (Hashtable)_htMapKey[strKeyVectorName];
			if (htKeys == null) return false;
			return htKeys.ContainsKey(objKey);
		}
		public int CountVector()
		{
			return _htMapValue.Count;
		}
		public int CountKeyVector()
		{
			return _htMapKey.Count;
		}
		public ArrayList GetVector(object strVectorName)
		{
			ArrayList alValues = (ArrayList)_htMapValue[strVectorName];
			return new ArrayList(alValues);
		}
		public ArrayList GetAllVectorName()
		{
			return new ArrayList(_htMapValue.Keys);
		}
		public ArrayList GetAllKeyVectorName()
		{
			return new ArrayList(_htMapKey.Keys);
		}
		public object GetValue(object strKeyVectorName, object objKey, object strVectorName)
		{
			Hashtable htKeys = (Hashtable)_htMapKey[strKeyVectorName];
			if (htKeys == null) return null;
			object objPos = htKeys[objKey];
			if (objPos == null) return null;
			int nPos = Convert.ToInt32(objPos);
			ArrayList alValues = (ArrayList)_htMapValue[strVectorName];
			if (alValues == null) return null;
			if (alValues.Count <= nPos) return null;
			return alValues[nPos];
		}
		public void VectorAddItem(object strVectorName, object objValue)
		{
			ArrayList alValues = (ArrayList)_htMapValue[strVectorName];
			if (alValues == null) return;
			alValues.Add(objValue);
			Hashtable htKeys = (Hashtable)_htMapKey[strVectorName];
			if (htKeys == null) return;
			htKeys.Add(objValue, htKeys.Count);
		}
		//public void VectorRemoveItem(object strVectorName, object objValue)
		//{
		//    ArrayList alValues = (ArrayList)_htMapValue[strVectorName];
		//    if (alValues == null) return;
		//    alValues.Remove(objValue);
		//    Hashtable htKeys = (Hashtable)_htMapKey[strVectorName];
		//    if (htKeys == null) return;
		//    htKeys.Remove(objValue);
		//}
		#endregion
	}

	public class CMyQueueConcurrence
	{
		#region // Constructors and Destructors:
		private object _objLockForQueue = new object();
		private ArrayList _alQueue = new ArrayList();
		public delegate void HandlerEnqueueDone(object[] arrobjItems);
		public event HandlerEnqueueDone EventEnqueueDone;
		public delegate void HandlerDequeueDone(object[] arrobjItems);
		public event HandlerDequeueDone EventDequeueDone;

		public CMyQueueConcurrence()
		{ 
		}
		#endregion

		#region // Public members:
		public void Enqueue(object objItem)
		{
			// Enqueue:
			lock (_objLockForQueue)
			{
				_alQueue.Add(objItem);
			}

			// Raise event:
			if (EventEnqueueDone != null) EventEnqueueDone(new object[]{objItem});
		}
		public void EnqueueMulti(object[] arrobjItems)
		{
			// Enqueue:
			if (arrobjItems == null || arrobjItems.Length < 1) return;
			lock (_objLockForQueue)
			{
				_alQueue.AddRange(arrobjItems);
			}

			// Raise event:
			if (EventEnqueueDone != null) EventEnqueueDone(arrobjItems);
		}
		public bool Dequeue(out object objItem)
		{
			// Dequeue:
			objItem = null;
			bool bResult = false;
			if (_alQueue.Count < 1) return bResult;
			lock (_objLockForQueue)
			{
				if (_alQueue.Count > 0)
				{
					bResult = true;
					objItem = _alQueue[0];
					_alQueue.RemoveAt(0);
				}
			}

			// Raise event:
			if (bResult && EventDequeueDone != null) EventDequeueDone(new object[] { objItem });

			// Return Good:
			return bResult;
		}
		public bool DequeueAll(out object[] arrobjItems)
		{
			// Dequeue:
			arrobjItems = null;
			bool bResult = false;
			if (_alQueue.Count < 1) return bResult;
			lock (_objLockForQueue)
			{
				if (_alQueue.Count > 0)
				{
					bResult = true;
					arrobjItems = _alQueue.ToArray();
					_alQueue.Clear();
				}
			}

			// Raise event:
			if (bResult && EventDequeueDone != null) EventDequeueDone(arrobjItems);

			// Return Good:
			return bResult;
		}
		#endregion
	}

	public class CMySeq
	{
		#region // Constructors and Destructors:
		public const string c_strFormat = "{0:yyyyMMdd.HHmmss.ffffff}.{1}";
		private long _nSeq = 0;
		private object _objLockForSeq = new object();
		private string _strFormat = c_strFormat;
		private long _nModulo = 0;
		private void Init(string strFormat, long nModulo)
		{
			_strFormat = strFormat;
			_nModulo = nModulo;
		}

		public CMySeq()
		{
			Init(c_strFormat, 0);
		}
		public CMySeq(string strFormat, long nModulo)
		{
			Init(strFormat, nModulo);
		}
		#endregion

		#region // Public members:
		public long GetNextSeq()
		{
			lock (_objLockForSeq)
			{
				return _nSeq++;
			}
		}
		public string GetNextSeqString()
		{
			if (_nModulo < 1)
			{
				return string.Format(_strFormat, DateTime.Now, this.GetNextSeq());
			}
			else
			{
				return string.Format(_strFormat, DateTime.Now, this.GetNextSeq() % _nModulo);
			}
		}
		#endregion
	}
}
